package com.example.java_gobang.game;

import com.example.java_gobang.model.User;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;

import java.io.IOException;
import java.util.LinkedList;
import java.util.Queue;

@Component
public class Matcher {
    @Autowired
    private ObjectMapper objectMapper;
    @Autowired
    RoomManager roomManager;

    @Autowired
    private OnlineUserManager onlineUserManager;

    //三个匹配队列
    private Queue<User> normalQueue = new LinkedList<>();
    private Queue<User> highQueue = new LinkedList<>();
    private Queue<User> veryHighQueue = new LinkedList<>();

    //加入匹配
    public void add(User user){
        if(user.getScore() < 2000){
           synchronized (normalQueue){
               normalQueue.offer(user);
               normalQueue.notify();
           }
            System.out.println("玩家：" + user.getUsername() + "加入normal队列");
        } else if (user.getScore() >= 2000 && user.getScore() < 3000) {
           synchronized (highQueue){
               highQueue.offer(user);
               highQueue.notify();
           }
            System.out.println("玩家：" + user.getUsername() + "加入high队列");
        }else {
           synchronized (veryHighQueue){
               veryHighQueue.offer(user);
               veryHighQueue.notify();
           }
            System.out.println("玩家：" + user.getUsername() + "加入veryHigh队列");
        }

    }

    //退出队列
    public void remove(User user){
        if(user.getScore() < 2000){
            synchronized (normalQueue){
                normalQueue.remove(user);
            }
            System.out.println("玩家：" + user.getUsername() + "退出normal队列");
        } else if (user.getScore() >= 2000 && user.getScore() < 3000) {
           synchronized (highQueue){
               highQueue.remove(user);
           }
            System.out.println("玩家：" + user.getUsername() + "退出high队列");
        }else {
            synchronized (veryHighQueue){
                veryHighQueue.remove(user);
            }
            System.out.println("玩家：" + user.getUsername() + "退出veryHigh队列");
        }
    }

    //开多线程同时扫描多个队列
    private Matcher(){
        Thread t1  = new Thread(){
            @Override
            public void run(){
                while(true){
                    handlerMatch(normalQueue);
                }
            }
        };
        t1.start();

        Thread t2  = new Thread(){
            @Override
            public void run(){
                while(true){
                    handlerMatch(highQueue);
                }
            }
        };
        t2.start();

        Thread t3  = new Thread(){
            @Override
            public void run(){
                while(true){
                    handlerMatch(veryHighQueue);
                }
            }
        };
        t3.start();
    }

    private void handlerMatch(Queue<User> queue)  {
        try {
            synchronized (queue){
                while(queue.size() < 2){
                    queue.wait();
                }
            }
            User player1 = queue.poll();
            User player2 = queue.poll();
            WebSocketSession session1 = onlineUserManager.getSessionByHall(player1.getUserId());
            WebSocketSession session2 = onlineUserManager.getSessionByHall(player2.getUserId());

            //判断玩家是否在线
            if(session1 == null){
                //把玩家2放回匹配队列
                queue.offer(player2);
                return;
            }

            if(session2 == null){
                queue.offer(player1);
                return;
            }

            if(session1 == session2){
                queue.offer(player1);
                return;
            }
            //将两个玩家添加到房间
            Room room = new Room();
            roomManager.add(room, player1.getUserId(), player2.getUserId());

            //给玩家发回响应数据
            MatchResponse response = new MatchResponse();
            response.setOk(true);
            response.setMessage("matchSuccess");
            session1.sendMessage(new TextMessage(objectMapper.writeValueAsString(response)));
            session2.sendMessage(new TextMessage(objectMapper.writeValueAsString(response)));
        } catch (IOException| InterruptedException e) {
            throw new RuntimeException(e);
        }
    }
}
